#pragma once
#include <vector>
#include <string>
#include "map"
#include "unordered_map"
#include "utility"
#include <iostream>

namespace FSM
{
	template <class InheritanceClassName, class Task, class State>
	class FSMBase
	{
	public:
		typedef void (InheritanceClassName::*FP)(State &);
		typedef bool (InheritanceClassName::*BFP)(const Task &, State &);
		virtual void Init() = 0; //default state; state regist ;event regist
		virtual void EventHandle(const Task &task, State &state) = 0;
		virtual void StateHandle(const std::string &state, State &ego_state) = 0;
		inline virtual void CreatStateActionTalbe(const std::string &state, FP fun_address)
		{
			state_action_table_[state] = fun_address;
		};
		inline virtual void MoveState(const std::string &to_state)
		{
			cur_state_ = to_state;
		};
		inline virtual void SetCurState(const std::string &to_state) //init
		{
			cur_state_ = to_state;
			last_state_ = to_state;
		};
		inline virtual void StateRegist(const std::string &state, FP fun_address)
		{
			states_table_.push_back(state);
			states_table_size_++;
			CreatStateActionTalbe(state, fun_address);
		};
		inline virtual void StateTransitionRegist(const std::string &curstate, const std::string &tostate, BFP transiton_condition)
		{
			state_transition_map_[curstate][tostate] = transiton_condition;
			if (last_state_ != curstate)
			{
				last_state_ = curstate;
				order_cout_ = 0;
				regist_order_[curstate][order_cout_] = tostate;
				order_cout_++;
			}
			else
			{

				regist_order_[curstate][order_cout_] = tostate;
				order_cout_++;
			}
		};
		virtual void FSMReset()
		{
			cur_state_ = "";
			last_state_ = "";
			order_cout_ = 0;
			states_table_size_ = 0;
			events_table_size_ = 0;
			states_table_.clear();
			event_table_.clear();
		};
		inline virtual const std::string &GetCurState()
		{
			return cur_state_;
		};
		inline virtual int GetCurStatesTableSize()
		{
			return states_table_size_;
		};
		inline virtual std::vector<std::string> GetStateTable()
		{
			return states_table_;
		};
		inline virtual std::vector<std::string> GetEventTable()
		{
			return event_table_;
		};
		inline virtual char GettransitionMapSize()
		{
			return state_transition_map_.size();
		};
		std::vector<std::string> states_table_;
		std::vector<std::string> event_table_;
		std::string cur_state_;
		int states_table_size_;
		int events_table_size_;
		std::map<FP, FP> event_action_table_;
		std::map<std::string, FP> state_action_table_;
		std::map<std::string, std::map<int, std::string>> regist_order_;
		int order_cout_ = 0;
		std::map<std::string, std::map<std::string, BFP>> state_transition_map_;
		std::string last_state_;
	};
} // namespace FSM